#include "pch.h"
#include "db_interface_mysql.h"
#include "db_transaction.h"
#include "db_exception.h"
#include "db_interface.h"
/*#include "helper/debug_helper.h"*/
/*#include "common/timestamp.h"*/
#include "mysqld_error.h"
#include "errmsg.h"


std::string SQL_START_TRANSACTION = "START TRANSACTION";
std::string SQL_ROLLBACK = "ROLLBACK";
std::string SQL_COMMIT = "COMMIT";

//-------------------------------------------------------------------------------------
DBTransaction::DBTransaction(DBInterface* dbi, bool autostart):
	dbi_(dbi),
	committed_(false),
	autostart_(autostart)
{
	if(autostart)
		start();
}

//-------------------------------------------------------------------------------------
DBTransaction::~DBTransaction()
{
	if(autostart_)
		end();
}

//-------------------------------------------------------------------------------------
void DBTransaction::start()
{
	committed_ = false;

	try
	{
		dbi_->query(SQL_START_TRANSACTION, false);
	}
	catch (DBException & e)
	{
		bool ret = static_cast<DBInterfaceMysql*>(dbi_)->processException(e);
		ASSERT(ret);
	}

	static_cast<DBInterfaceMysql*>(dbi_)->inTransaction(true);
}

//-------------------------------------------------------------------------------------
void DBTransaction::end()
{
	if (!committed_ && !static_cast<DBInterfaceMysql*>(dbi_)->hasLostConnection())
	{
		try
		{
			LogWarn( "DBTransaction::~DBTransaction: "
					"Rolling back\n" );

			dbi_->query(SQL_ROLLBACK, false);
		}
		catch (DBException & e)
		{
			if (e.isLostConnection())
			{
				static_cast<DBInterfaceMysql*>(dbi_)->hasLostConnection(true);
			}
		}
	}

	static_cast<DBInterfaceMysql*>(dbi_)->inTransaction(false);
}

//-------------------------------------------------------------------------------------
bool DBTransaction::shouldRetry() const
{
	return (dbi_->getlasterror() == ER_LOCK_DEADLOCK);
}

//-------------------------------------------------------------------------------------
void DBTransaction::commit()
{
	ASSERT(!committed_);

	uint64 startTime = TimeUtil::GetMilliSecond();
	dbi_->query(SQL_COMMIT, false);

	uint64 duration = TimeUtil::GetMilliSecond() - startTime;
	if(duration > 200)
	{
		LogWarn("DBTransaction::commit(): took {%u} seconds\n", 
			duration);
	}

	committed_ = true;
}


